#include <iostream>
#include <string>
#include <unordered_map>
#include <set>
#include <vector>
#include <sw/redis++/redis++.h>
#include <chrono>
#include <thread>

#include "util.hpp"

using std::cout;
using std::cin;
using std::string;
using std::endl;
using std::unordered_map;
using std::vector;
using std::set;

using sw::redis::Redis;
using sw::redis::StringView;

using namespace std::chrono_literals;

void Sadd(Redis& redis) {
    redis.flushdb();

    redis.sadd("key", "1");

    redis.sadd("key", {"2", "3", "4"});

    set<string> input = {"5", "6", "7"};
    redis.sadd("key", input.begin(), input.end());

    set<string> output;
    // set 里面没有 push_back 函数，所以无法使用 back_inserter
    // auto it = std::back_inserter(output);
    // 由于 set 是无序的，指定任何地方的迭代器都无所谓
    auto it = std::inserter(output, output.begin());
    // 查询 set 中的所有元素
    redis.smembers("key", it);

    Print(output);
}

void Sismember(Redis& redis) {
    redis.flushdb();
    redis.sadd("key", {"1", "2", "3", "4"});

    bool ret = redis.sismember("key", "1");
}

void Scard(Redis& redis) {
    redis.flushdb();
    redis.sadd("key", {"1", "2", "3", "4"});

    // 获取元素个数
    long long size = redis.scard("key");
    cout << "size = " << size << endl;
}

// 随机删除元素
void Spop(Redis& redis) {
    redis.flushdb();
    redis.sadd("key", {"1", "2", "3", "4"});

    // 返回值是 OptionalString, 因为 key 可能是不存在
    auto ret = redis.spop("key");
    if (ret) {
        cout << "result = " << ret.value() << endl;
    }
}

// 求交集
void Sinter(Redis& redis) {
    redis.flushdb();
    redis.sadd("key1", {"1", "2", "3", "4"});

    redis.sadd("key2", {"3", "4", "5", "6"});

    // 第一个参数可以是：initializer<T>, 表示要求交集的 Key 个数
    set<string> res_set;
    auto it = std::inserter(res_set, res_set.end());
    redis.sinter({"key1", "key2"}, it);

    Print(res_set);
}

void Sinterstore(Redis& redis) {
    redis.flushdb();
    redis.sadd("key1", {"1", "2", "3", "4"});

    redis.sadd("key2", {"3", "4", "5", "6"});

    // 返回值：交集的元素个数
    redis.sinterstore("key3", {"key1", "key2"});
    
    set<string> result;
    auto it = std::inserter(result, result.end());
    redis.smembers("key3", it);

    Print(result);
}


int main() {
    Redis redis("tcp://127.0.0.1:6379");

    Sadd(redis);

    Sismember(redis);

    Scard(redis);

    Spop(redis);

    Sinter(redis);

    Sinterstore(redis);

    return 0;
}